package com.example.democlient.network;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.ArrayDeque;
import java.util.Deque;
import android.util.Log;
import com.example.democlient.MyApplication;
import com.example.democlient.network.handler.PacketHandler;
import com.example.democlient.network.packet.ClientPacket;
import com.example.democlient.network.packet.ServerPacket;


public class ServerConnection extends NetConnection
{

	/**
	 * Possible states of CsConnection
	 */
	public static enum State
	{
		/**
		 * chat server just connected
		 */
		CONNECTED,
		/**
		 * chat server is authenticated
		 */
		AUTHED
	}
	
	private final Deque<ServerPacket>	sendMsgQueue	= new ArrayDeque<ServerPacket>();

	/**
	 * Current state of this connection
	 */
	private State						state;
	private PacketHandler				packetHandler;
	
	/**
	 * @param sc
	 * @param d
	 * @throws IOException
	 */

	public ServerConnection(SocketChannel sc, Dispatcher d, PacketHandler packetHandler) throws IOException
	{
		super(sc, d);
		this.packetHandler = packetHandler;
		state = State.CONNECTED;
		Log.i("succeed","Connected to LogicServer!");
	}

	@Override
	public boolean processData(ByteBuffer data)
	{
		ClientPacket pck = packetHandler.handle(data, this);
		Log.i("processData","recived packet: " + pck);

		/**
		 * Execute packet only if packet exist (!= null) and read was ok.
		 */
		if(pck != null && pck.read()){
			Log.i("执行线程","begin");
			ThreadPoolManager.getInstance().executeLsPacket(pck);
		}

		return true;
	}

	@Override
	protected final boolean writeData(ByteBuffer data)
	{
		synchronized(guard)
		{
			ServerPacket packet = sendMsgQueue.pollFirst();
			if(packet == null)
				return false;

			packet.write(this, data);
			return true;
		}
	}

	@Override
	protected final long getDisconnectionDelay()
	{
		return 0;
	}

	@Override
	protected final void onDisconnect()
	{
	}

	@Override
	public final void onServerClose()
	{
		onlyClose();
	}

	/**
	 * @param bp
	 */
	public final void sendPacket(ServerPacket bp,MyApplication myApp)
	{
		synchronized(guard)
		{
			/**
			 * Connection is already closed or waiting for last (close packet) to be sent
			 */
			if(isWriteDisabled())
				return;

			//super.handler = mHandler;
			super.app = myApp;
			sendMsgQueue.addLast(bp);
			enableWriteInterest();
		}
	}
	public final void sendPacket(ServerPacket bp)
	{
		synchronized(guard)
		{
			/**
			 * Connection is already closed or waiting for last (close packet) to be sent
			 */
			if(isWriteDisabled())
				return;

			sendMsgQueue.addLast(bp);
			enableWriteInterest();
		}
	}
	/**
	 * 
	 * @param closePacket
	 * @param forced
	 */
	public final void close(ServerPacket closePacket, boolean forced)
	{
		synchronized(guard)
		{
			if(isWriteDisabled())
				return;

			pendingClose = true;
			isForcedClosing = forced;
			sendMsgQueue.clear();
			sendMsgQueue.addLast(closePacket);
			enableWriteInterest();
		}
	}

	/**
	 * @return
	 */
	public State getState()
	{
		return state;
	}

	/**
	 * @param state
	 */
	public void setState(State state)
	{
		this.state = state;
	}

	@Override
	public String toString()
	{
		return "Server " + getIP();
	}
}
